package com.chasing.baseframe.service.download;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.DownloadManager;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import com.chasing.baseframe.MyApplication;
import com.hwangjr.rxbus.annotation.Subscribe;
import com.hwangjr.rxbus.annotation.Tag;
import com.hwangjr.rxbus.thread.EventThread;

import net.chasing.androidbaseconfig.util.ActivityUtils;
import net.chasing.androidbaseconfig.util.AppUtils;
import net.chasing.androidbaseconfig.util.DialogUtils;
import net.chasing.androidbaseconfig.util.NetUtils;
import net.chasing.androidbaseconfig.util.RxBusUtils;
import net.chasing.androidbaseconfig.util.TimeUtils;
import net.chasing.androidbaseconfig.util.permission.PermissionUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class LoadManager {
    private static final int HANDLE_DOWNLOAD = 1;
    private static LoadManager mLoadManager;

    private final List<DownloadBean> mDownloadBeanList;
    // 下载任务执行器
    private DownloadManager downloadManager;
    private DownloadWork.DownloadReceiver recevier;
    private final IntentFilter intentFilter;

    private DownloadChangeObserver downloadObserver;
    private ScheduledExecutorService scheduledExecutorService;

    @SuppressLint("HandlerLeak")
    public final Handler downLoadHandler = new Handler(Looper.getMainLooper()) { //主线程的handler
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            Activity activity = ActivityUtils.getActivityUtils().currentActivity();
            if (activity != null && HANDLE_DOWNLOAD == msg.what) {
                try {
                    if (msg.obj != null) {
                        DownloadBean downloadBean = (DownloadBean) msg.obj;

                        int[] bytesAndStatus = getBytesAndStatus(downloadBean.id);
                        int errorReason = bytesAndStatus[0];
                        if (errorReason > 0 && errorReason != DownloadManager.PAUSED_WAITING_FOR_NETWORK) {
                            // 下载失败
                            mDownloadBeanList.remove(downloadBean);
                            releaseResource(activity);
                            return;
                        }
                        int downCurrentSize = bytesAndStatus[1];
                        int downTotalSize = bytesAndStatus[2];
                        // 被除数可以为0，除数必须大于0
                        if (downCurrentSize >= 0 && downTotalSize > 0) {
                            // 创建一个数值格式化对象
                            int currentProgress = (int) (downCurrentSize * 100L / downTotalSize);
                            downloadBean.progress = currentProgress;

                            boolean isMax = currentProgress >= 100;
                            Log.i("VideoProcess", "安装包下载进度：" + currentProgress);
                            if (isMax) {
                                // 下载完成
                                Intent intent = new Intent(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
                                intent.putExtra(DownloadManager.EXTRA_DOWNLOAD_ID, downloadBean.id);
                                LocalBroadcastManager.getInstance(activity).sendBroadcast(intent);
                            }
                        }
                    }
                } catch (Exception ignored) {
                }
            }
        }
    };

    private final Runnable progressRunnable = this::updateProgress;

    private LoadManager() {
        mDownloadBeanList = new ArrayList<>();
        intentFilter = new IntentFilter();
        intentFilter.addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
    }

    public static LoadManager getInstance() {
        if (mLoadManager == null) {
            mLoadManager = new LoadManager();
        }
        return mLoadManager;
    }

    // title是显示在通知栏上的下载标题，fileName是定义存储文件名
    public void addRequest(Context context, String url, String title, String fileName) {
        DownloadBean downloadBean = new DownloadBean();
        downloadBean.url = url;
        if (fileName.contains("."))
            fileName = fileName.substring(0, fileName.lastIndexOf(".")) + "_" +
                    TimeUtils.long2String(System.currentTimeMillis(), "yyyyMMddHHmmss") +
                    fileName.substring(fileName.lastIndexOf("."));
        downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
        // 允许媒体扫描，根据下载的文件类型被加入相册、音乐等媒体库
        request.allowScanningByMediaScanner();
        // 允许在计费流量下下载
//        request.setAllowedOverMetered(false);
        // 允许该记录在下载管理界面可见
        request.setVisibleInDownloadsUi(false);
        // 允许漫游时下载
        request.setAllowedOverRoaming(true);
        request.setMimeType("application/vnd.android.package-archive");
        // 设置通知的显示类型
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
        // 允许下载的网路类型
//        request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
        request.setTitle(title);
        // 下载到对外的私有目录下。部分机型读取系统download目录会没有权限
        downloadBean.file = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), fileName);
        request.setDestinationUri(Uri.fromFile(downloadBean.file));

        downloadBean.downloadRequest = request;
        mDownloadBeanList.add(downloadBean);
    }

    public void download(FragmentActivity activity, String downUrl, String title, String name) {
        if (!PermissionUtils.requestStoragePermission(activity, isAllGranted -> {
            if (isAllGranted)
                download(activity, downUrl, title, name);
        })) {
            if (!NetUtils.isConnected(MyApplication.INSTANCE)) {
                return;
            }

            int enableFlag = downLoadMangerIsEnable(activity);
            if (enableFlag != 1) {
                DialogUtils.createDialog(activity, enableFlag == 0 ?
                                "下载管理器被禁用，请前往设置界面进行开启后重试！" :
                                "未检查到下载管理器，请前往设置界面查看下载管理器是否正常！", "前往设置界面",
                        v -> openDownloadSettingPage(activity)).show();
            } else {
                DownloadWork.startWork(activity.getApplicationContext(), downUrl, title, name);
            }
        }
    }

    /**
     * 检测下载管理器是否可用, 1 可用 0 不可用 -1 查询异常，未检测到：
     * java.lang.IllegalArgumentException
     * Unknown package: com.android.providers.downloads
     */
    private static int downLoadMangerIsEnable(Context context) {
        try {
            int state = context.getApplicationContext().getPackageManager()
                    .getApplicationEnabledSetting("com.android.providers.downloads");
            return state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED ||
                    state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER
                    || state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED ? 0 : 1;
        } catch (Exception e) {
            return -1;
        }
    }

    // 调启系统下载设置界面
    private void openDownloadSettingPage(Context context) {
        try {
            //Open the specific App Info page:
            Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
            intent.setData(Uri.parse("package:" + "com.android.providers.downloads"));
            context.startActivity(intent);
        } catch (ActivityNotFoundException e) {
            //Open the generic Apps page:
            Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS);
            context.startActivity(intent);
        }
    }

    // 注册ContentObserver
    public void registerContentObserver(Context context) {
        if (recevier == null && intentFilter != null) {
            recevier = new DownloadWork.DownloadReceiver();
            LocalBroadcastManager.getInstance(context).registerReceiver(recevier, intentFilter);
        }

        /* observer download change **/
        if (downloadObserver == null) {
            downloadObserver = new DownloadChangeObserver();
            context.getContentResolver().registerContentObserver(
                    Uri.parse("content://downloads/my_downloads"), false, downloadObserver);
        }
    }

    // 注销ContentObserver
    public void unregisterContentObserver(Context context) {
        if (downloadObserver != null) {
            context.getContentResolver().unregisterContentObserver(downloadObserver);
            downloadObserver = null;
        }
    }

    // 执行下载
    public void enqueue() {
        for (int i = 0; i < mDownloadBeanList.size(); i++) {
            DownloadBean downloadBean = mDownloadBeanList.get(i);
            if (downloadBean.id == 0) {
                if (downloadBean.file.exists()) downloadBean.file.delete();
                downloadBean.id = downloadManager.enqueue(downloadBean.downloadRequest);
                mDownloadBeanList.set(i, downloadBean);
            }
        }
    }

    // 取消下载并删除下载文件
    public boolean remove(String url) {
        boolean hadRemove = false;
        if (!TextUtils.isEmpty(url))
            for (DownloadBean downloadBean : mDownloadBeanList) {
                if (url.equals(downloadBean.url)) {
                    downloadManager.remove(downloadBean.id);
                    hadRemove = true;
                    break;
                }
            }
        return hadRemove;
    }

    /**
     * 调用方需要实现BroadcastReceive监听DownloadManager.ACTION_DOWNLOAD_COMPLETE
     * onReceive内部： taskId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
     */
    public void onDownloadComplete(Context context, long taskId) {
        try {
            for (DownloadBean downloadBean : mDownloadBeanList) {
                if (downloadBean.id == taskId) {
                    DownloadManager.Query myDownloadQuery = new DownloadManager.Query();
                    myDownloadQuery.setFilterById(taskId);
                    Cursor myDownload = downloadManager.query(myDownloadQuery);
                    if (myDownload != null) {
                        myDownload.close();
                    }
                    installApk(taskId);
                    mDownloadBeanList.remove(downloadBean);
                    releaseResource(context);
                    break;
                }
            }
        } catch (Exception ignored) {
        }
    }

    // 关闭定时器，线程等释放资源操作
    private void releaseResource(Context context) {
        if (mDownloadBeanList.isEmpty()) {
            if (scheduledExecutorService != null && !scheduledExecutorService.isShutdown()) {
                scheduledExecutorService.shutdown();
                scheduledExecutorService = null;
            }
            downLoadHandler.removeCallbacksAndMessages(null);
            unregisterContentObserver(context);

            Activity activity = ActivityUtils.getActivityUtils().currentActivity();
            if (activity != null && recevier != null) {
                LocalBroadcastManager.getInstance(activity).unregisterReceiver(recevier);
                recevier = null;
            }
            RxBusUtils.unregister(this);
        }
    }

    /**
     * 发送Handler消息更新进度和状态
     * 将查询结果从子线程中发往主线程（handler方式），以防止ANR
     */
    private void updateProgress() {
        for (DownloadBean downloadBean : mDownloadBeanList) {
            if (downloadBean.id > 0) {
                downLoadHandler.sendMessage(downLoadHandler.obtainMessage(HANDLE_DOWNLOAD, downloadBean));
            }
        }
    }

    // 安装apk
    private void installApk(long taskId) {
        for (DownloadBean downloadBean : mDownloadBeanList) {
            if (downloadBean.id == taskId) {
                if (downloadBean.file == null || !downloadBean.file.exists())
                    break;
                install(downloadBean.file.getAbsolutePath());
                break;
            }
        }
    }

    private void install(String filePath) {
        AppUtils.installApk(filePath, false);
    }

    public class DownloadChangeObserver extends ContentObserver {

        public DownloadChangeObserver() {
            super(downLoadHandler);
            scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
        }

        /**
         * 当所监听的Uri发生改变时，就会回调此方法
         *
         * @param selfChange 此值意义不大, 一般情况下该回调值false
         */
        @Override
        public void onChange(boolean selfChange) {
            scheduledExecutorService.scheduleAtFixedRate(progressRunnable, 0, 2, TimeUnit.SECONDS);
        }
    }

    /**
     * 通过query查询下载状态，包括已下载数据大小，总大小，下载状态
     */
    private int[] getBytesAndStatus(long downloadId) {
        int[] bytesAndStatus = new int[]{
                -1, -1, -1, 0
        };
        DownloadManager.Query query = new DownloadManager.Query().setFilterById(downloadId);

        try (Cursor cursor = downloadManager.query(query)) {
            if (cursor != null && cursor.moveToFirst()) {
                bytesAndStatus[0] = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_REASON));
                //已经下载文件大小
                bytesAndStatus[1] = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
                //下载文件的总大小
                bytesAndStatus[2] = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
                //下载状态
                bytesAndStatus[3] = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS));
            }
        } catch (Exception ignored) {
        }
        return bytesAndStatus;
    }

    @Subscribe(
            thread = EventThread.MAIN_THREAD,
            tags = {
                    @Tag("StoragePermission")
            }
    )
    public void onGetStoragePermission(Boolean isHavePermission) {
        if (isHavePermission) {
            Activity activity = ActivityUtils.getActivityUtils().currentActivity();
            if (mDownloadBeanList != null)
                for (DownloadBean downloadBean : mDownloadBeanList) {
                    if (!TextUtils.isEmpty(downloadBean.url)) {
                        download((FragmentActivity) activity, downloadBean.url, downloadBean.file.getName(), downloadBean.file.getName());
                    }
                }
        }
    }
}
